home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Scope / Scope Disk #142 (199x)(Scope PD)(US)[WB].zip / Scope Disk #142 (199x)(Scope PD)(US)[WB].adf / LoadImage / RexxHostLib.c < prev    next >
C/C++ Source or Header  |  1990-07-30  |  12KB  |  556 lines

  1. /* $Revision Header * Header built automatically - do not edit! *************
  2.  *
  3.  *    (C) Copyright 1990 by MXM
  4.  *
  5.  *    Name .....: RexxHostLib.c
  6.  *    Created ..: Sunday 07-Jan-90 18:55
  7.  *    Revision .: 12
  8.  *
  9.  *    Date            Author          Comment
  10.  *    =========       ========        ====================
  11.  *    26-Apr-90       Olsen           Supports short integers (16 bits)
  12.  *    13-Apr-90       Olsen           Added assembly language routines
  13.  *    31-Mar-90       Olsen           Rewrote RexxStrCmp
  14.  *    19-Mar-90       Olsen           More sanity checks
  15.  *    17-Mar-90       Olsen           Added RexxStrCmp, rewrote
  16.  *                                    CreateRexxHost/DeleteRexxHost,
  17.  *                                    ANSIfication
  18.  *    16-Mar-90       Olsen           Rework for Aztec 5.0 release
  19.  *    07-Jan-90       Olsen           Added string conversion functions
  20.  *    07-Jan-90       Olsen           Added GetToken
  21.  *    07-Jan-90       Olsen           - Empty log message -
  22.  *    07-Jan-90       Olsen           Removed bug in SendRexxCommand
  23.  *    07-Jan-90       Olsen           - Empty log message -
  24.  *    07-Jan-90       Olsen           Created this file!
  25.  *
  26.  ****************************************************************************
  27.  *
  28.  *    This Amiga shared library is based on example source code
  29.  *    written by Gary Samad & Bill Hawes.
  30.  *
  31.  * $Revision Header ********************************************************/
  32.  #define REVISION 12
  33.  
  34.     /* The protos. */
  35.  
  36. struct RexxMsg    *CreateRexxMsg(struct MsgPort *,char *,char *);
  37. STRPTR         CreateArgstring(char *,LONG);
  38. VOID         DeleteRexxMsg(struct RexxMsg *);
  39. VOID         DeleteArgstring(char *);
  40. STATIC LONG     AmigaToUpper(LONG);
  41.  
  42.     /* The magic pragma. */
  43.  
  44. #pragma regcall(AmigaToUpper(d0))
  45.  
  46.     /* Bill Hawes didn't distribute an .fd file along
  47.      * with the 1.10 release of ARexx. I had to put these
  48.      * pragmas together by hand.
  49.      */
  50.  
  51. #pragma amicall(RexxSysBase, 0x90, CreateRexxMsg(a0,a1,d0))
  52. #pragma amicall(RexxSysBase, 0x7e, CreateArgstring(a0,d0))
  53. #pragma amicall(RexxSysBase, 0x96, DeleteRexxMsg(a0))
  54. #pragma amicall(RexxSysBase, 0x84, DeleteArgstring(a0))
  55.  
  56.     /* Global revision identifier. */
  57.  
  58. LONG Revision = REVISION;
  59.  
  60.     /* CreateRexxHost(HostName):
  61.      *
  62.      *    Creates a RexxHost (special MsgPort) with a given name.
  63.      *    Returns NULL if port already exists.
  64.      */
  65.  
  66. struct RexxHost *
  67. CreateRexxHost(STRPTR HostName)
  68. {
  69.     struct RexxHostBase    *RexxHostBase;
  70.     struct RexxHost        *RexxHost = NULL;
  71.  
  72.         /* Our pointer to ExecBase. */
  73.  
  74.     extern struct ExecBase    *SysBase;
  75.  
  76.     if(HostName && HostName[0])
  77.     {
  78.             /* Already present? */
  79.  
  80.         if(!FindPort((char *)HostName))
  81.         {
  82.             LONG SigBit;
  83.  
  84.                 /* Allocate a signal bit. */
  85.  
  86.             if((SigBit = AllocSignal(-1)) == -1)
  87.                 goto Quit;
  88.  
  89.                 /* Allocate the port body. */
  90.  
  91.             if(!(RexxHost = (struct RexxHost *)AllocMem(sizeof(struct RexxHost),MEMF_PUBLIC | MEMF_CLEAR)))
  92.             {
  93.                 FreeSignal(SigBit);
  94.                 goto Quit;
  95.             }
  96.  
  97.                 /* Initialize the MsgPort node head. */
  98.  
  99.             RexxHost -> rh_Port . mp_Node . ln_Type    = NT_MSGPORT;
  100.             RexxHost -> rh_Port . mp_Node . ln_Pri    = 1;
  101.  
  102.                 /* Allocate memory for MsgPort name. */
  103.  
  104.             if(!(RexxHost -> rh_Port . mp_Node . ln_Name = (char *)AllocMem(StrLen((char *)HostName) + 1,MEMF_PUBLIC)))
  105.             {
  106.                 FreeMem(RexxHost,sizeof(struct RexxHost));
  107.                 FreeSignal(SigBit);
  108.  
  109.                 RexxHost = NULL;
  110.  
  111.                 goto Quit;
  112.             }
  113.  
  114.                 /* Copy the name. */
  115.  
  116.             StrCpy(RexxHost -> rh_Port . mp_Node . ln_Name,(char *)HostName);
  117.  
  118.                 /* Deal with the rest of the flags. */
  119.  
  120.             RexxHost -> rh_Port . mp_Flags        = PA_SIGNAL;
  121.             RexxHost -> rh_Port . mp_SigBit        = SigBit;
  122.             RexxHost -> rh_Port . mp_SigTask    = SysBase -> ThisTask;
  123.  
  124.                 /* A dummy ID. */
  125.  
  126.             RexxHost -> rh_SpecialID = 'REXX';
  127.  
  128.                 /* Finally add it to the public port list. */
  129.  
  130.             AddPort(&RexxHost -> rh_Port);
  131.         }
  132.     }
  133.  
  134. Quit:    return(RexxHost);
  135. }
  136.  
  137.     /* DeleteRexxHost(RexxHost):
  138.      *
  139.      *    Deletes a MsgPort as created by CreateRexxHost().
  140.      *    Returns NULL, so user can do 'Host = DeleteRexxHost(Host);'.
  141.      */
  142.  
  143. VOID *
  144. DeleteRexxHost(struct RexxHost *RexxHost)
  145. {
  146.     struct RexxHostBase *RexxHostBase;
  147.  
  148.     if(RexxHost && RexxHost -> rh_SpecialID == 'REXX')
  149.     {
  150.             /* Remove it from the public list. */
  151.  
  152.         RemPort(&RexxHost -> rh_Port);
  153.  
  154.             /* Make it difficult to reuse it by accident. */
  155.  
  156.         RexxHost -> rh_Port . mp_Node . ln_Type        = 0xFF;
  157.         RexxHost -> rh_Port . mp_MsgList . lh_Head    = (struct Node *)-1;
  158.  
  159.             /* Free the name. */
  160.  
  161.         FreeMem(RexxHost -> rh_Port . mp_Node . ln_Name,StrLen(RexxHost -> rh_Port . mp_Node . ln_Name) + 1);
  162.  
  163.             /* Free the allocated signal bit. */
  164.  
  165.         FreeSignal(RexxHost -> rh_Port . mp_SigBit);
  166.  
  167.             /* Free the body. */
  168.  
  169.         FreeMem(RexxHost,sizeof(struct RexxHost));
  170.     }
  171.  
  172.     return(NULL);
  173. }
  174.  
  175.     /* SendRexxCommand(HostPort,CommandString,FileExtension,HostName):
  176.      *
  177.      *    Sends a command to the rexx server, requires pointers
  178.      *    to the MsgPort of the calling Host and the command string.
  179.      *    File extension and host name are optional and may be
  180.      *    NULL.
  181.      */
  182.  
  183. LONG
  184. SendRexxCommand(struct RexxHost *HostPort,STRPTR CommandString,STRPTR FileExtension,STRPTR HostName)
  185. {
  186.     struct RexxHostBase *RexxHostBase;
  187.  
  188.     struct MsgPort    *RexxPort = (struct MsgPort *)FindPort(RXSDIR);
  189.     struct RexxMsg    *HostMessage;
  190.  
  191.         /* Valid pointers given? */
  192.  
  193.     if(!CommandString || !HostPort || HostPort -> rh_SpecialID != 'REXX' || !RexxPort)
  194.         return(FALSE);
  195.  
  196.         /* No special host name given? Take the MsgPort name. */
  197.  
  198.     if(!HostName)
  199.         HostName = (STRPTR)HostPort -> rh_Port . mp_Node . ln_Name;
  200.  
  201.         /* No file name extension? Take the default. */
  202.  
  203.     if(!FileExtension)
  204.         FileExtension = (STRPTR)"rexx";
  205.  
  206.         /* Create the message. */
  207.  
  208.     if(!(HostMessage = CreateRexxMsg((struct MsgPort *)HostPort,(char *)FileExtension,(char *)HostName)))
  209.         return(FALSE);
  210.  
  211.         /* Add the command. */
  212.  
  213.     if(!(HostMessage -> rm_Args[0] = CreateArgstring((char *)CommandString,StrLen((char *)CommandString))))
  214.     {
  215.         DeleteRexxMsg(HostMessage);
  216.         return(FALSE);
  217.     }
  218.  
  219.         /* This is a command, not a function. */
  220.  
  221.     HostMessage -> rm_Action = RXCOMM;
  222.  
  223.         /* Release it... */
  224.  
  225.     PutMsg(RexxPort,HostMessage);
  226.  
  227.         /* Successful action. */
  228.  
  229.     return(TRUE);
  230. }
  231.  
  232.     /* FreeRexxCommand(RexxMessage):
  233.      *
  234.      *    Frees the contents of a RexxMsg.
  235.      */
  236.  
  237. VOID
  238. FreeRexxCommand(struct RexxMsg *RexxMessage)
  239. {
  240.     struct RexxHostBase *RexxHostBase;
  241.  
  242.         /* Valid pointer given? */
  243.  
  244.     if(RexxMessage && RexxMessage -> rm_Node . mn_Node . ln_Type == NT_REPLYMSG)
  245.     {
  246.             /* Remove argument. */
  247.  
  248.         if(RexxMessage -> rm_Args[0])
  249.             DeleteArgstring((char *)RexxMessage -> rm_Args[0]);
  250.  
  251.             /* Free the message. */
  252.  
  253.         DeleteRexxMsg(RexxMessage);
  254.     }
  255. }
  256.  
  257.     /* ReplyRexxCommand(RexxMessage,Primary,Secondary,Result):
  258.      *
  259.      *    Sends a RexxMsg back to the rexx server, can include
  260.      *    result codes.
  261.      */
  262.  
  263. VOID
  264. ReplyRexxCommand(struct RexxMsg *RexxMessage,LONG Primary,LONG Secondary,STRPTR Result)
  265. {
  266.     struct RexxHostBase *RexxHostBase;
  267.  
  268.         /* Valid pointer given? */
  269.  
  270.     if(RexxMessage && RexxMessage -> rm_Node . mn_Node . ln_Type == NT_MESSAGE)
  271.     {
  272.             /* No secondary result and results wanted? */
  273.  
  274.         if(Secondary == NULL && (RexxMessage -> rm_Action & RXFF_RESULT))
  275.         {
  276.                 /* Build result string... */
  277.  
  278.             if(Result)
  279.                 Secondary = (LONG)CreateArgstring((char *)Result,StrLen((char *)Result));
  280.         }
  281.  
  282.             /* Set both results... */
  283.  
  284.         RexxMessage -> rm_Result1 = Primary;
  285.         RexxMessage -> rm_Result2 = Secondary;
  286.  
  287.             /* ...and reply the message. */
  288.  
  289.         ReplyMsg(RexxMessage);
  290.     }
  291. }
  292.  
  293.     /* GetRexxCommand(RexxMessage):
  294.      *
  295.      *    Returns a pointer to the command string if
  296.      *    the RexxMsg is a command request.
  297.      */
  298.  
  299. STRPTR
  300. GetRexxCommand(struct RexxMsg *RexxMessage)
  301. {
  302.     struct RexxHostBase *RexxHostBase;
  303.  
  304.     if(!RexxMessage || RexxMessage -> rm_Node . mn_Node . ln_Type == NT_REPLYMSG)
  305.         return(NULL);
  306.     else
  307.         return(RexxMessage -> rm_Args[0]);
  308. }
  309.  
  310.     /* GetRexxArg(RexxMessage):
  311.      *
  312.      *    Returns a pointer to the first RexxMsg argument.
  313.      */
  314.  
  315. STRPTR
  316. GetRexxArg(struct RexxMsg *RexxMessage)
  317. {
  318.     struct RexxHostBase *RexxHostBase;
  319.  
  320.     if(!RexxMessage)
  321.         return(NULL);
  322.     else
  323.         return(RexxMessage -> rm_Args[0]);
  324. }
  325.  
  326.     /* GetRexxResult1(RexxMessage):
  327.      *
  328.      *    Returns the 1st RexxMsg result.
  329.      */
  330.  
  331. LONG
  332. GetRexxResult1(struct RexxMsg *RexxMessage)
  333. {
  334.     struct RexxHostBase *RexxHostBase;
  335.  
  336.     if(!RexxMessage)
  337.         return(NULL);
  338.     else
  339.         return(RexxMessage -> rm_Result1);
  340. }
  341.  
  342.     /* GetRexxResult2(RexxMessage):
  343.      *
  344.      *    Returns the 2nd RexxMsg result.
  345.      */
  346.  
  347. LONG
  348. GetRexxResult2(struct RexxMsg *RexxMessage)
  349. {
  350.     struct RexxHostBase *RexxHostBase;
  351.  
  352.     if(!RexxMessage)
  353.         return(NULL);
  354.     else
  355.         return(RexxMessage -> rm_Result2);
  356. }
  357.  
  358.     /* GetToken(String,StartChar,AuxBuff,MaxLength):
  359.      *
  360.      *    Fills a string with the next given string
  361.      *    argument.
  362.      */
  363.  
  364. STRPTR
  365. GetToken(STRPTR String,LONG *StartChar,STRPTR AuxBuff,LONG MaxLength)
  366. {
  367.     struct RexxHostBase *RexxHostBase;
  368.  
  369.     LONG i,StrEnd = 0,MaxPos = StrLen((char *)String);
  370.  
  371.         /* Last counter position. */
  372.  
  373.     if(MaxPos >= MaxLength)
  374.         MaxPos = MaxLength - 1;
  375.  
  376.         /* Already finished with argument string? */
  377.  
  378.     if(*StartChar > StrLen((char *)String) - 1 || !String || !String[0] || !AuxBuff || !MaxLength)
  379.         return(NULL);
  380.  
  381.         /* Parse the argument string... */
  382.  
  383.     for(i = *StartChar ; i <= MaxPos ; i++)
  384.     {
  385.             /* Skip leading blanks... */
  386.  
  387.         if(!StrEnd && String[i] == ' ')
  388.         {
  389.             while(String[i] == ' ' && i < MaxPos)
  390.             {
  391.                 i++;
  392.  
  393.                 (*StartChar)++;
  394.             }
  395.         }
  396.  
  397.             /* Found an argument. */
  398.  
  399.         if(String[i] == ' ' || String[i] == 0)
  400.         {
  401.                 /* Copy it to the auxiliary buffer. */
  402.  
  403.             StrNCpy((char *)AuxBuff,(char *)(String + *StartChar),StrEnd);
  404.             AuxBuff[StrEnd] = 0;
  405.  
  406.                 /* Change the position counter (since
  407.                  * we can't use static data initialisation
  408.                  * calling program has to supply a
  409.                  * counter variable).
  410.                  */
  411.  
  412.             (*StartChar) += StrEnd;
  413.  
  414.             return(AuxBuff);
  415.         }
  416.  
  417.             /* Increment character counter. */
  418.  
  419.         StrEnd++;
  420.     }
  421.  
  422.     return(NULL);
  423. }
  424.  
  425.     /* GetStringValue(String):
  426.      *
  427.      *    Returns the numeric value taken from given string
  428.      *    (just like atoi(), taken from example source code
  429.      *    by K&R).
  430.      */
  431.  
  432. LONG
  433. GetStringValue(STRPTR String)
  434. {
  435.     struct RexxHostBase *RexxHostBase;
  436.  
  437.     LONG i,Value,Sign = 1;
  438.  
  439.         /* Valid argument given? */
  440.  
  441.     if(!String || !String[0])
  442.         return(0);
  443.  
  444.         /* Skip leading blank characters. */
  445.  
  446.     for(i = 0 ; String[i] == ' ' || String[i] == '\n' || String[i] == '\t' ; i++);
  447.  
  448.         /* Remember sign extension. */
  449.  
  450.     if(String[i] == '+' || String[i] == '-')
  451.         Sign = (String[i++] == '+') ? 1 : -1;
  452.  
  453.         /* Convert from ASCII to decimal. */
  454.  
  455.     for(Value = 0 ; String[i] >= '0' && String[i] <= '9' ; i++)
  456.         Value = 10 * Value + String[i] - '0';
  457.  
  458.         /* Return real value. */
  459.  
  460.     return(Sign * Value);
  461. }
  462.  
  463.     /* BuildValueString(Value,String):
  464.      *
  465.      *    Puts a numeric value in decimal form into a
  466.      *    given string (similar to itoa(), taken from
  467.      *    example source code by K&R).
  468.      */
  469.  
  470. STRPTR
  471. BuildValueString(LONG Value,STRPTR String)
  472. {
  473.     struct RexxHostBase *RexxHostBase;
  474.  
  475.     LONG i = 0,j,c,Sign;
  476.  
  477.         /* Valid argument given? */
  478.  
  479.     if(!String)
  480.         return(NULL);
  481.  
  482.         /* Remember sign extension. */
  483.  
  484.     if((Sign = Value) < 0)
  485.         Value = -Value;
  486.  
  487.         /* Convert it into ASCII characters (in
  488.          * reverse order, i.e. 1234 = "4321").
  489.          */
  490.  
  491.     do
  492.         String[i++] = Value % 10 + '0';
  493.     while((Value /= 10) > 0);
  494.  
  495.         /* Add sign extension. */
  496.  
  497.     if(Sign < 0)
  498.         String[i++] = '-';
  499.  
  500.         /* String NULL-termination. */
  501.  
  502.     String[i] = 0;
  503.  
  504.         /* Reverse the string. */
  505.  
  506.     for(i = 0, j = StrLen((char *)String) - 1 ; i < j ; i++, j--)
  507.     {
  508.         c        = String[i];
  509.         String[i]    = String[j];
  510.         String[j]    = c;
  511.     }
  512.  
  513.         /* Finished, return the string. */
  514.  
  515.     return(String);
  516. }
  517.  
  518.     /* AmigaToUpper(c):
  519.      *
  520.      *    Replacement for toupper() macro, also knows how to
  521.      *    map international characters to uppercase. Note: not
  522.      *    a real library module.
  523.      */
  524.  
  525. STATIC LONG
  526. AmigaToUpper(LONG c)
  527. {
  528.     /* -------- DEC ---------    -------- ASCII ------- */
  529.  
  530.     if((c >= 224 && c <= 254) || (c >= 'a' && c <= 'z'))
  531.         c -= 32;
  532.  
  533.     return(c);
  534. }
  535.  
  536.     /* RexxStrCmp(Source,Target):
  537.      *
  538.      *    Compares two strings ignoring case.
  539.      */
  540.  
  541. LONG
  542. RexxStrCmp(STRPTR Source,STRPTR Target)
  543. {
  544.     struct RexxHostBase *RexxHostBase;
  545.  
  546.         /* Do the string comparison ignoring case. */
  547.  
  548.     for( ; AmigaToUpper(*Source) == AmigaToUpper(*Target) ; Source++, Target++)
  549.     {
  550.         if(!(*Source))
  551.             return(0);
  552.     }
  553.  
  554.     return(AmigaToUpper(*Source) - AmigaToUpper(*Target));
  555. }
  556.